/** * * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. * */ package com.noisepages.nettoyeur.libpd.sample; import java.nio.ByteBuffer; import java.nio.ShortBuffer; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import org.puredata.core.PdBase; /** * * Simple example of how to use libpd with JavaSound. This example currently only does audio output, * but it's easy enough to add support for audio input. * * Note that the simple expedient of requesting a source data line from AudioSystem may not be sound on systems * with multiple sound cards or other complications. In general, you will need to deal with mixers and other * subtleties. * * @author Peter Brinkmann (peter.brinkmann@gmail.com) * */ public class JavaSoundThread extends Thread { private final float sampleRate; // Sample rate in Hz. private final int outChans; // Number of output channels. private final int ticks; // Number of Pd ticks per buffer. private volatile boolean terminated; public JavaSoundThread(float sampleRate, int outChans, int ticks) { this.sampleRate = sampleRate; this.outChans = outChans; this.ticks = ticks; PdBase.openAudio(0, outChans, (int) sampleRate); PdBase.computeAudio(true); setPriority(Thread.MAX_PRIORITY); } @Override public void run() { terminated = false; try { perform(); } catch (LineUnavailableException e) { e.printStackTrace(); } } @Override public void interrupt() { terminated = true; // Needed since the interrupted flag is cleared by JavaSound. super.interrupt(); } private void perform() throws LineUnavailableException { // JavaSound setup. int sampleSize = 2; AudioFormat audioFormat = new AudioFormat(sampleRate, 8 * sampleSize, outChans, true, true); DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(info); sourceDataLine.open(audioFormat); sourceDataLine.start(); // Buffer setup for exchanging samples between libpd and JavaSound. // Question: Is this the best possible solution? It seems to involve too // much copying. int frames = PdBase.blockSize() * ticks; short[] dummy = new short[0]; short[] samples = new short[frames * outChans]; byte[] rawSamples = new byte[samples.length * sampleSize]; ByteBuffer buf = ByteBuffer.wrap(rawSamples); ShortBuffer shortBuf = buf.asShortBuffer(); while (!terminated) { // Note: sourceDataLine.write seems to clear the interrupted flag, and so Thread.interrupted() doesn't work here. PdBase.process(ticks, dummy, samples); shortBuf.rewind(); shortBuf.put(samples); sourceDataLine.write(rawSamples, 0, rawSamples.length); } // Shutdown. sourceDataLine.drain(); sourceDataLine.stop(); sourceDataLine.close(); } }